package com.cheyun.netsalev3.widget

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.text.TextPaint
import android.util.AttributeSet
import android.util.TypedValue
import android.view.MotionEvent
import android.view.View
import androidx.annotation.Nullable
import com.cheyun.netsalev3.R
import java.util.*

/**
 * @author Michael
 * @date  2018/12/24 - 9:46.
 * 字母快速滑动view
 */


class AZSideBarView @JvmOverloads constructor(context: Context, @Nullable attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {

    private var mBackgroundColor: Int = 0
    private var mStrokeColor: Int = 0
    private var mTextColor: Int = 0
    private var mTextSize: Int = 0
    private var mSelectTextColor: Int = 0
    private var mSelectTextSize: Int = 0
    private var mHintTextColor: Int = 0
    private var mHintTextSize: Int = 0
    private var mHintCircleRadius: Int = 0
    private var mHintCircleColor: Int = 0
    private var mHintShape: Int = 0
    private var mContentPadding: Int = 0
    private var mBarPadding: Int = 0
    private var mBarWidth: Int = 0

    private var mLetters: List<String>? = null
    private var mSlideBarRect: RectF? = null
    private var mTextPaint: TextPaint? = null
    private var mPaint: Paint? = null
    private var mSelect: Int = 0
    private var mPreSelect: Int = 0
    private var mNewSelect: Int = 0
    private var mRatioAnimator: ValueAnimator? = null
    private var mAnimationRatio: Float = 0.toFloat()
    private var mListener: OnLetterChangeListener? = null
    private var mTouchY: Int = 0

    init {
        initAttribute(attrs, defStyleAttr)
        initData()
    }

    private fun initAttribute(attrs: AttributeSet?, defStyleAttr: Int) {
        val typeArray = context.obtainStyledAttributes(attrs, R.styleable.AZSideBarView, defStyleAttr, 0)
        mBackgroundColor = typeArray.getColor(R.styleable.AZSideBarView_backgroundColor, Color.parseColor("#F9F9F9"))
        mStrokeColor = typeArray.getColor(R.styleable.AZSideBarView_strokeColor, Color.parseColor("#000000"))
        mTextColor = typeArray.getColor(R.styleable.AZSideBarView_textColor, Color.parseColor("#969696"))
        mTextSize = typeArray.getDimensionPixelOffset(R.styleable.AZSideBarView_textSize,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10f,
                        resources.displayMetrics).toInt())
        mSelectTextColor = typeArray.getColor(R.styleable.AZSideBarView_selectTextColor, Color.parseColor("#FF0000"))
        mSelectTextSize = typeArray.getDimensionPixelOffset(R.styleable.AZSideBarView_selectTextSize,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10f,
                        resources.displayMetrics).toInt())
        mHintTextColor = typeArray.getColor(R.styleable.AZSideBarView_hintTextColor, Color.parseColor("#FFFFFF"))
        mHintTextSize = typeArray.getDimensionPixelOffset(R.styleable.AZSideBarView_hintTextSize,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16f,
                        resources.displayMetrics).toInt())
        mHintCircleRadius = typeArray.getDimensionPixelOffset(R.styleable.AZSideBarView_hintCircleRadius,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24f,
                        resources.displayMetrics).toInt())
        mHintCircleColor = typeArray.getColor(R.styleable.AZSideBarView_hintCircleColor, Color.parseColor("#52D5E9"))
        mHintShape = typeArray.getInteger(R.styleable.AZSideBarView_hintShape, 1)
        mContentPadding = typeArray.getDimensionPixelOffset(R.styleable.AZSideBarView_contentPadding,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2f,
                        resources.displayMetrics).toInt())
        mBarPadding = typeArray.getDimensionPixelOffset(R.styleable.AZSideBarView_barPadding,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6f,
                        resources.displayMetrics).toInt())
        mBarWidth = typeArray.getDimensionPixelOffset(R.styleable.AZSideBarView_barWidth,
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f,
                        resources.displayMetrics).toInt())
        if (mBarWidth == 0) {
            mBarWidth = 2 * mTextSize
        }
        typeArray.recycle()
    }

    private fun initData() {
        mLetters = Arrays.asList(*context.resources.getStringArray(R.array.slide_bar_value_list))
        mTextPaint = TextPaint()
        mPaint = Paint()
        mPaint!!.isAntiAlias = true
        mSelect = -1
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        if (mSlideBarRect == null) {
            mSlideBarRect = RectF()
        }
        val contentLeft = (measuredWidth - mBarWidth - mBarPadding).toFloat()
        val contentRight = (measuredWidth - mBarPadding).toFloat()
        val contentTop = mBarPadding.toFloat()
        val contentBottom = (measuredHeight - mBarPadding).toFloat()
        mSlideBarRect!!.set(contentLeft, contentTop, contentRight, contentBottom)

    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        //绘制slide bar 上字母列表
        drawLetters(canvas)
        //绘制选中时的提示信息(圆＋文字)
        drawHint(canvas)
        //绘制选中的slide bar上的那个文字
        drawSelect(canvas)
    }

    /**
     * 绘制slide bar 上字母列表
     */
    private fun drawLetters(canvas: Canvas) {
        //绘制圆角矩形
        mPaint!!.style = Paint.Style.FILL
        mPaint!!.color = mBackgroundColor
        canvas.drawRoundRect(mSlideBarRect!!, mBarWidth / 2.0f, mBarWidth / 2.0f, mPaint!!)
        //顺序绘制文字
        val itemHeight = (mSlideBarRect!!.bottom - mSlideBarRect!!.top - (mContentPadding * 2).toFloat()) / mLetters!!.size
        for (index in mLetters!!.indices) {
            val baseLine = TextDrawUtils.getTextBaseLineByCenter(
                    mSlideBarRect!!.top + mContentPadding.toFloat() + itemHeight * index + itemHeight / 2,
                    this!!.mTextPaint!!, mTextSize)
            mTextPaint!!.color = mTextColor
//            mTextPaint!!.textSize = if (0 == index) mTextSize.toFloat() * 2 else mTextSize.toFloat()
            mTextPaint!!.textSize = mTextSize.toFloat()
            mTextPaint!!.textAlign = Paint.Align.CENTER
            val pointX = mSlideBarRect!!.left + (mSlideBarRect!!.right - mSlideBarRect!!.left) / 2.0f
            canvas.drawText(mLetters!![index], pointX, baseLine, mTextPaint!!)
        }
    }

    /**
     * 绘制选中时的提示信息(圆＋文字)
     */
    private fun drawSelect(canvas: Canvas) {
        if (mSelect != -1) {
            mTextPaint!!.color = mSelectTextColor
//            var size = if (mSelect == 0) mSelectTextSize.toFloat() * 2 else mSelectTextSize.toFloat()
            var size = mSelectTextSize.toFloat()
            mTextPaint!!.textSize = size
            mTextPaint!!.textAlign = Paint.Align.CENTER
            val itemHeight = (mSlideBarRect!!.bottom - mSlideBarRect!!.top - (mContentPadding * 2).toFloat()) / mLetters!!.size
            val baseLine = TextDrawUtils.getTextBaseLineByCenter(
                    mSlideBarRect!!.top + mContentPadding.toFloat() + itemHeight * mSelect + itemHeight / 2, mTextPaint!!, size.toInt())
            val pointX = mSlideBarRect!!.left + (mSlideBarRect!!.right - mSlideBarRect!!.left) / 2.0f
            canvas.drawText(mLetters!![mSelect], pointX, baseLine, mTextPaint!!)
        }
    }

    /**
     * 绘制选中的slide bar上的那个文字
     */
    private fun drawHint(canvas: Canvas) {
        //x轴的移动路径
        val circleCenterX = measuredWidth + mHintCircleRadius - (-measuredWidth / 2 + (measuredWidth + mHintCircleRadius)) * 1.0f
        mPaint!!.style = Paint.Style.FILL
        mPaint!!.color = mHintCircleColor
        mPaint!!.alpha = (255 * mAnimationRatio).toInt()
        if (mHintShape == 0) {
            canvas.drawCircle(circleCenterX, measuredHeight / 2.0f, mHintCircleRadius.toFloat(), mPaint!!)
        } else {
            var r = RectF()
            r.set(circleCenterX - mHintCircleRadius, measuredHeight / 2.0f - mHintCircleRadius,
                    circleCenterX + mHintCircleRadius, measuredHeight / 2.0f + mHintCircleRadius)
            canvas.drawRoundRect(r, mHintCircleRadius.toFloat() / 4, mHintCircleRadius.toFloat() / 4, mPaint!!)
        }
        // 绘制圆中心的提示字符
        if (mSelect != -1) {
            var size = if (mSelect == 0) mHintTextSize.toFloat() * 2 else mHintTextSize.toFloat()
            val target = mLetters!![mSelect]
            val textY = TextDrawUtils.getTextBaseLineByCenter(measuredHeight / 2.0f, this!!.mTextPaint!!, size.toInt())
            mTextPaint!!.color = mHintTextColor
            mTextPaint!!.textSize = size
            mTextPaint!!.textAlign = Paint.Align.CENTER
            canvas.drawText(target, circleCenterX, textY, mTextPaint!!)
        }
    }

    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        val y = event.y
        val x = event.x
        mPreSelect = mSelect
        mNewSelect = (y / (mSlideBarRect!!.bottom - mSlideBarRect!!.top) * mLetters!!.size).toInt()
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                if (x < mSlideBarRect!!.left || y < mSlideBarRect!!.top || y > mSlideBarRect!!.bottom) {
                    return false
                }
                mTouchY = y.toInt()
                startAnimator(1.0f)
            }
            MotionEvent.ACTION_MOVE -> {
                mTouchY = y.toInt()
                if (mPreSelect != mNewSelect) {
                    if (mNewSelect >= 0 && mNewSelect < mLetters!!.size) {
                        mSelect = mNewSelect
                        if (mListener != null) {
                            mListener!!.onLetterChange(mLetters!![mNewSelect])
                        }
                    }
                }
                invalidate()
            }
            MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
                startAnimator(1f,true)
                mSelect = -1
            }
            else -> {
            }
        }
        return true
    }

    private fun startAnimator(temvalue: Float, isClose: Boolean = false) {
        if (mRatioAnimator == null) {
            mRatioAnimator = ValueAnimator()
        }
        mRatioAnimator!!.cancel()
        mRatioAnimator!!.setFloatValues(temvalue)
        mRatioAnimator!!.addUpdateListener { value ->
            mAnimationRatio = if (isClose) {
                1 - value.animatedValue as Float
            } else {
                1f
            }

            //球弹到位的时候，并且点击的位置变了，即点击的时候显示当前选择位置
            if (mAnimationRatio == 1f && mPreSelect != mNewSelect) {
                if (mNewSelect >= 0 && mNewSelect < mLetters!!.size) {
                    mSelect = mNewSelect
                    if (mListener != null) {
                        mListener!!.onLetterChange(mLetters!![mNewSelect])
                    }
                }
            }
            invalidate()
        }
        mRatioAnimator!!.start()
    }

    fun setOnLetterChangeListener(listener: OnLetterChangeListener) {
        this.mListener = listener
    }

    interface OnLetterChangeListener {

        fun onLetterChange(letter: String)
    }
}


